require 'test/unit'
require 'semantictext/document' 
require 'semantictext/default_tag_factory'
require 'semantictext/httptag'


class TestDocument < Test::Unit::TestCase

	def assert_element(element_class, text, actual)
	  assert_equal element_class, actual.class
	  assert_equal text, actual.text
  end

  def test_regression_doesnt_crash
    factory = SemanticText::DefaultTagFactory.new
    factory.register_tag('img',SemanticText::HTTPTag)
    unit = SemanticText::Document.new(factory)
    unit.parse_from(ENV['SANDBOX']+'/semantictext/testfiles/exploder.art')
  end

	def test_end_to_end_loading
		unit = SemanticText::Document.new
		unit.parse_from(ENV['SANDBOX']+'/semantictext/testfiles/simple.art')
		assert_equal 'test title', unit.title
		assert_equal 5, unit.createdAt.day
		assert_equal 11, unit.createdAt.month
		assert_equal 2005, unit.createdAt.year
		assert_equal Time, unit.createdAt.class
		assert_equal ENV['SANDBOX']+'/semantictext/testfiles/simple.art', unit.pathname

    resultant_heading = unit.content[0]
    resultant_par0 = unit.content[1]
    resultant_span0_0 = resultant_par0.content[0]
    resultant_span0_1 = resultant_par0.content[1]
    resultant_par1 = unit.content[2]
    resultant_span1_0 = resultant_par1.content[0]
    
    assert_element SemanticText::Heading, "First Big Heading", resultant_heading

    assert_equal SemanticText::Paragraph, resultant_par0.class
    assert_element SemanticText::Span, 'This is another', resultant_span0_0
    assert_element SemanticText::Span, 'paragraph.', resultant_span0_1
    
    assert_equal SemanticText::Paragraph, resultant_par1.class
    assert_element SemanticText::Span, 'Theis is the second paragraph.', resultant_span1_0
  end
	

  	def test_headerless_document_parse
  		unit = SemanticText::Document.new
  		test_lines = <<EOF
!First Big Heading

This is some text.
EOF
      test_lines.each {|line| unit.parse(line)}

      assert_element SemanticText::Heading, "First Big Heading", unit.content[0]
      assert_equal SemanticText::Paragraph, unit.content[1].class
      assert_element SemanticText::Span, "This is some text.", unit.content[1].content[0]
      assert_nil unit.title
      assert_nil unit.createdAt
      assert_nil unit.keywords
  	end

    def test_parse_paragraph_beginning_with_url
        		unit = SemanticText::Document.new
        		test_lines = <<EOF

http://www.dafydd.net/foogoo?blah see? http://www.example.com
I wonder if it worked!
EOF
            test_lines.each {|line| unit.parse(line)}
            result = unit.content[0]
            assert_equal SemanticText::Paragraph, result.class
            assert_element SemanticText::HTTPTag, "//www.dafydd.net/foogoo?blah", result.content[0]
            assert_element SemanticText::Span, " see? ", result.content[1]
            assert_element SemanticText::HTTPTag, "//www.example.com", result.content[2]
            assert_element SemanticText::Span, "I wonder if it worked!", result.content[3]
            assert_equal 4, result.content.size    
    end
    
  	def test_headerless_document_parse_with_url
  		unit = SemanticText::Document.new
  		test_lines = <<EOF

Embedded link http://www.dafydd.net/foogoo?blah see?
I wonder if it worked!
a mailto:foogoo b ftp://host/path c
EOF
      test_lines.each {|line| unit.parse(line)}

      result = unit.content[0]
      assert_equal SemanticText::Paragraph, result.class
      assert_element SemanticText::Span, "Embedded link ", result.content[0]
      assert_element SemanticText::HTTPTag, "//www.dafydd.net/foogoo?blah", result.content[1]
      assert_element SemanticText::Span, " see?", result.content[2]
      assert_element SemanticText::Span, "I wonder if it worked!", result.content[3]
      assert_element SemanticText::Span, 'a ', result.content[4]
      assert_element SemanticText::MailToTag, 'foogoo', result.content[5]
      assert_element SemanticText::Span, ' b ', result.content[6]
      assert_element SemanticText::FTPTag, '//host/path', result.content[7]
      assert_element SemanticText::Span, ' c', result.content[8]
      assert_equal 9, result.content.size
  	end
      	
	def test_paragraph_parsing
		unit = SemanticText::Document.new
		test_lines = <<EOF
title:test title
createdAt:5 November 2005
keywords: buzz, fuzz, muzz

!First Big Heading

This is another
paragraph.

Theis is the second paragraph.

EOF
    test_lines.each {|line| unit.parse(line)}

    assert_element SemanticText::Heading, "First Big Heading", unit.content[0]
    assert_equal SemanticText::Paragraph, unit.content[1].class
    assert_element SemanticText::Span, "This is another", unit.content[1].content[0]
    assert_element SemanticText::Span, "paragraph.", unit.content[1].content[1]

    assert_equal SemanticText::Paragraph, unit.content[2].class
    assert_element SemanticText::Span, "Theis is the second paragraph.", unit.content[2].content[0]
    assert_equal 3, unit.content.size
	end

	def test_parsing_of_parameters
		unit = SemanticText::Document.new
		unit.parse('title:test title')
		unit.parse('createdAt:5 November 2005')
		unit.parse('keywords: buzz, fuzz, muzz')
		unit.parse('')

		assert_equal 'test title', unit.title
		assert_equal 5, unit.createdAt.day
		assert_equal 11, unit.createdAt.month
		assert_equal 2005, unit.createdAt.year
		assert_equal Time, unit.createdAt.class
		assert unit.keywords == ['buzz', 'fuzz', 'muzz']
		assert_equal 3, unit.keywords.size		
		assert_nil   unit.pathname
		assert	     unit.parameters_complete?
	end
	
	def test_presendence_of_url_lower_than_tag
    		unit = SemanticText::Document.new
    		unit.parse('')
    		unit.parse('Embedded tag [http://www.dafydd.net/foogoo?blah name:here] see?')

        result = unit.content[0]
        assert_equal SemanticText::Paragraph, result.class
        assert_element SemanticText::Span, "Embedded tag ", result.content[0]
        assert_element SemanticText::HTTPTag, "//www.dafydd.net/foogoo?blah name:here", result.content[1]
        assert_element SemanticText::Span, " see?", result.content[2]
        assert_equal 3, result.content.size
  end
  
	def test_headerless_document_parse_with_tags
    		unit = SemanticText::Document.new
    		test_lines = <<EOF

Embedded tag [mailto:fred@example.com] see?
I wonder if it worked!
a [ftp://ftp.example.com/stuff/download] b [http://www.example.com] c
EOF
        test_lines.each {|line| unit.parse(line)}

        result = unit.content[0]
        assert_equal SemanticText::Paragraph, result.class
        assert_element SemanticText::Span, "Embedded tag ", result.content[0]
        assert_element SemanticText::MailToTag, "fred@example.com", result.content[1]
        assert_element SemanticText::Span, " see?", result.content[2]
        assert_element SemanticText::Span, "I wonder if it worked!", result.content[3]
        assert_element SemanticText::Span, 'a ', result.content[4]
        assert_element SemanticText::FTPTag, '//ftp.example.com/stuff/download', result.content[5]
        assert_element SemanticText::Span, ' b ', result.content[6]
        assert_element SemanticText::HTTPTag, '//www.example.com', result.content[7]
        assert_element SemanticText::Span, ' c', result.content[8]
        assert_equal 9, result.content.size
    	end

  def test_heading_parsing
    unit = SemanticText::Document.new
    unit.parse ''
    unit.parse '!1st level heading'
    unit.parse '!!2nd level heading'
    unit.parse '!!!3rd level heading'
    
    first_heading = unit.content[0]
    second_heading = unit.content[1]
    third_heading = unit.content[2]
    
    assert_equal "1st level heading", first_heading.text
    assert_equal SemanticText::Heading, first_heading.class
    assert_equal 1, first_heading.depth
    
    
    assert_equal "2nd level heading", second_heading.text
    assert_equal SemanticText::Heading, second_heading.class
    assert_equal 2, second_heading.depth
    
    assert_equal "3rd level heading", third_heading.text
    assert_equal SemanticText::Heading, third_heading.class
    assert_equal 3, third_heading.depth
  end
  
	def test_paragraphs_headings_and_bullet_points
    unit = SemanticText::Document.new
    unit.parse('')
    unit.parse('!heading')
    unit.parse('This is a paragraph')
    unit.parse('*   bullet point')
    unit.parse('** nested bullet point')
    unit.parse('')
    unit.parse('* separate list')

    assert_element SemanticText::Heading, "heading", unit.content[0]
    assert_equal SemanticText::Paragraph, unit.content[1].class
    assert_element SemanticText::Span, "This is a paragraph", unit.content[1].content[0]
    assert_equal SemanticText::BulletedList, unit.content[2].class
    
    bullets = unit.content[2]
    assert_equal 2, bullets.content.size
    
    bullet_1 = bullets.content[0]
    assert_equal SemanticText::Bullet, bullet_1.class
    assert_equal SemanticText::Span, bullet_1.content[0].class
    assert_equal 1, bullet_1.content.size
    assert_equal "bullet point", bullet_1.content[0].text
    
    nested = bullets.content[1]
    assert_equal SemanticText::BulletedList, nested.class
    assert_equal 1, nested.content.size
    
    nested_bullet = nested.content[0]
    
    assert_equal SemanticText::Bullet, nested_bullet.class
    assert_equal "nested bullet point", nested_bullet.content[0].text
    
    second_bullets = unit.content[3]
    assert_equal SemanticText::BulletedList, second_bullets.class
    assert_equal 1, second_bullets.size
    
    assert_equal SemanticText::Bullet, second_bullets.content[0].class
    assert_equal SemanticText::Span, second_bullets.content[0].content[0].class
    assert_equal "separate list", second_bullets.content[0].content[0].text
	end
	
	def test_bullet_points_with_urls_and_tags
    unit = SemanticText::Document.new
    unit.parse('')
    unit.parse('* with url http://www.example.com see?')
    unit.parse('* with tag [http://www.example.com] see?')

    actual_list = unit.content[0]
    first_bullet = actual_list.content[0]
    second_bullet = actual_list.content[1]
    
    assert_equal SemanticText::BulletedList, actual_list.class

    assert_element SemanticText::Span, 'with url ', first_bullet.content[0]
    assert_element SemanticText::HTTPTag, '//www.example.com', first_bullet.content[1]
    assert_element SemanticText::Span, ' see?', first_bullet.content[2]

    assert_element SemanticText::Span, 'with tag ', second_bullet.content[0]
    assert_element SemanticText::HTTPTag, '//www.example.com', second_bullet.content[1]
    assert_element SemanticText::Span, ' see?', second_bullet.content[2]    
	end
	
	def test_bulleted_list_nesting
    unit = SemanticText::Document.new
    unit.parse('')
    unit.parse('* separate list')
    unit.parse('** nested bullet point 1')
    unit.parse('** nested bullet point 2')
    unit.parse('* top-level bullet point')

    list = unit.content[0]
    assert_equal SemanticText::BulletedList, list.class
    assert_equal 3, list.content.size
    
    bullet_1 = list.content[0]
    assert_equal SemanticText::Bullet, bullet_1.class
    assert_equal SemanticText::Span, bullet_1.content[0].class
    assert_equal 'separate list', bullet_1.content[0].text
    
    nested = list.content[1]
    assert_equal SemanticText::BulletedList, nested.class
    assert_equal 2, nested.content.size
    
    bullet_2_1 = nested.content[0]
    assert_equal SemanticText::Bullet, bullet_2_1.class
    assert_equal SemanticText::Span, bullet_2_1.content[0].class
    assert_equal "nested bullet point 1", bullet_2_1.content[0].text

    bullet_2_2 = nested.content[1]
    assert_equal SemanticText::Bullet, bullet_2_2.class
    assert_equal SemanticText::Span, bullet_2_2.content[0].class
    assert_equal "nested bullet point 2", bullet_2_2.content[0].text
    
    bullet_3 = list.content[2]
    assert_equal SemanticText::Bullet, bullet_3.class
    assert_equal SemanticText::Span, bullet_3.content[0].class
    assert_equal "top-level bullet point", bullet_3.content[0].text
  end
  
	def test_bulleted_lsit_parsing_into_two_separate_lists
	  unit = SemanticText::Document.new
    unit.parse('')
    unit.parse('* first bullet in first list')
    unit.parse('')
    unit.parse('* second bullet in second list')

    assert_equal SemanticText::BulletedList, unit.content[0].class
    assert_equal SemanticText::BulletedList, unit.content[1].class
    
    assert_not_same(unit.content[0], unit.content[1])
  end
  
end
